package jp.seraph.jsade.effector;

import java.util.ArrayList;
import java.util.List;

import jp.seraph.jsade.math.AngleVelocity;
import jp.seraph.jsade.message.MessageUtil;
import jp.seraph.jsade.model.Joint;
import jp.seraph.jsade.util.NaoEffectorCreator;

/**
 * Nao用のEfectorBuilder実装です。<br>
 * 使用可能なEffectorKindはNaoEffectorKindのみです。
 *
 *
 */
public class NaoEffectorBuilder implements EffectorBuilder {
    public NaoEffectorBuilder(){
        mEffectors = new ArrayList<Effector>();
        mCreator = new NaoEffectorCreator();
    }

    private List<Effector> mEffectors;
    private NaoEffectorCreator mCreator;

    /**
     * Jointを動作させるエフェクタの引数と実際の角速度との比
     * 実際の角速度 = VELOCITY_FACTOR * エフェクタ引数
     */
    private final double VELOCITY_FACTOR = 1.15;

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#clear()
     */
    public void clear() {
        mEffectors.clear();
    }

    /**
     * 引数のaKindがNaoEffectorKindに存在するかどうかをチェックする。
     *
     * @param aKind
     * @return チェックが通ればtrue 駄目ならfalse
     */
    private boolean checkEffectorKind(EffectorKind aKind){
        if(aKind instanceof NaoEffectorKind)
            return true;

        return NaoEffectorKind.containsEffectorName(aKind.toString());
    }

    private void throwIllegalArgumentException(EffectorKind aKind) throws IllegalArgumentException{
        throw new IllegalArgumentException(MessageUtil.isNotNaoEffector(aKind));
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.Effector)
     */
    public void append(Effector aEffector) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector.getKind()))
            mEffectors.add(aEffector);
        else
            throwIllegalArgumentException(aEffector.getKind());
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, double[])
     */
    public void append(EffectorKind aEffector, double... aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, double)
     */
    public void append(EffectorKind aEffector, double aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, int[])
     */
    public void append(EffectorKind aEffector, int... aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, int)
     */
    public void append(EffectorKind aEffector, int aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, java.lang.String[])
     */
    public void append(EffectorKind aEffector, String... aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#append(jp.seraph.jsade.effector.EffectorKind, java.lang.String)
     */
    public void append(EffectorKind aEffector, String aValue) throws IllegalArgumentException {
        if(checkEffectorKind(aEffector))
            mEffectors.add(new DefaultEffector(aEffector, aValue));
        else
            throwIllegalArgumentException(aEffector);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#appendBeam(double, double, double)
     */
    public void appendBeam(double aX, double aY, double aZ) throws IllegalArgumentException {
        mEffectors.add(mCreator.createBeamEffector(aX, aY, aZ));
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#appendSay(java.lang.String)
     */

    public void appendSay(String aMessage) {
        mEffectors.add(mCreator.createSayEffector(aMessage));
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#appendJoint(jp.seraph.jsade.model.Joint, double)
     */
    public void appendJoint(Joint aTargetJoint, double aValue) throws IllegalArgumentException {
         mEffectors.add(mCreator.createJointEffector(aTargetJoint, aValue));
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#appendJoint(jp.seraph.jsade.model.Joint, jp.seraph.jsade.math.AngleVelocity)
     */
    public void appendJoint(Joint aTargetJoint, AngleVelocity aVelocity) throws IllegalArgumentException {
        this.appendJoint(aTargetJoint, aVelocity.getDegree() / VELOCITY_FACTOR);
    }

    /**
     *
     * @see jp.seraph.jsade.effector.EffectorBuilder#buildEffector()
     */
    public List<Effector> buildEffector() {
        return new ArrayList<Effector>(mEffectors);
    }


}
